package com.ease.plugin.traits {
	import com.ease.core.plugin.ResourceBase;
	import com.ease.plugin.events.LoadEvent;
	import com.ease.plugin.events.LoaderEvent;
	import com.ease.plugin.utils.PluginStrings;
	
	import flash.errors.IllegalOperationError;


	public class LoadTrait extends TraitBase {
		public function LoadTrait(loader:LoaderBase, resource:ResourceBase) {
			super(TraitType.LOAD);

			this.loader = loader;
			_resource = resource;
			_loadState = LoadState.UNINITIALIZED;

			if (loader != null) {
				loader.addEventListener(LoaderEvent.LOAD_STATE_CHANGE, onLoadStateChange, false, int.MAX_VALUE, true);
			}
		}

		public function get resource():ResourceBase {
			return _resource;
		}

		public function get loadState():String {
			return _loadState;
		}

		public function load():void {
			if (loader) {
				if (_loadState == LoadState.READY) {
					throw new IllegalOperationError(PluginStrings.getString(PluginStrings.ALREADY_READY));
				}
				if (_loadState == LoadState.LOADING) {
					throw new IllegalOperationError(PluginStrings.getString(PluginStrings.ALREADY_LOADING));
				}
				else {
					loader.load(this);
				}
			}
			else {
				throw new IllegalOperationError(PluginStrings.getString(PluginStrings.MUST_SET_LOADER));
			}
		}

		public function unload():void {
			if (loader) {
				if (_loadState == LoadState.UNLOADING) {
					throw new IllegalOperationError(PluginStrings.getString(PluginStrings.ALREADY_UNLOADING));
				}
				if (_loadState == LoadState.UNINITIALIZED) {
					throw new IllegalOperationError(PluginStrings.getString(PluginStrings.ALREADY_UNLOADED));
				}
				loader.unload(this);
			}
			else {
				throw new IllegalOperationError(PluginStrings.getString(PluginStrings.MUST_SET_LOADER));
			}
		}

		public function get bytesLoaded():Number {
			return _bytesLoaded;
		}

		public function get bytesTotal():Number {
			return _bytesTotal;
		}

		protected final function setLoadState(newState:String):void {
			if (_loadState != newState) {
				loadStateChangeStart(newState);

				_loadState = newState;

				loadStateChangeEnd();
			}
		}

		protected final function setBytesLoaded(value:Number):void {
			if (isNaN(value) || value > bytesTotal || value < 0) {
				throw new ArgumentError(PluginStrings.getString(PluginStrings.INVALID_PARAM));
			}

			if (value != _bytesLoaded) {
				bytesLoadedChangeStart(value);

				_bytesLoaded = value;

				bytesLoadedChangeEnd();
			}
		}

		protected final function setBytesTotal(value:Number):void {
			if (value < _bytesLoaded || value < 0) {
				throw new ArgumentError(PluginStrings.getString(PluginStrings.INVALID_PARAM));
			}

			if (value != _bytesTotal) {
				bytesTotalChangeStart(value);

				_bytesTotal = value;

				bytesTotalChangeEnd();
			}
		}

		protected function bytesLoadedChangeStart(newValue:Number):void {
		}

		protected function bytesLoadedChangeEnd():void {
		}

		protected function bytesTotalChangeStart(newValue:Number):void {
		}

		protected function bytesTotalChangeEnd():void {
			dispatchEvent(new LoadEvent(LoadEvent.BYTES_TOTAL_CHANGE, false, false, null, _bytesTotal));
		}

		protected function loadStateChangeStart(newState:String):void {
		}

		protected function loadStateChangeEnd():void {
			dispatchEvent(new LoadEvent(LoadEvent.LOAD_STATE_CHANGE, false, false, _loadState));
		}

		private function onLoadStateChange(event:LoaderEvent):void {
			if (event.loadTrait == this) {
				setLoadState(event.newState);
			}
		}

		private var loader:LoaderBase;
		private var _resource:ResourceBase;

		private var _loadState:String;

		private var _bytesLoaded:Number;
		private var _bytesTotal:Number;
	}
}